package scottb.cribbage.model {
import flash.utils.clearInterval;
import flash.utils.getTimer;
import flash.utils.setInterval;

import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
import mx.events.CollectionEventKind;

import scottb.cribbage.model.Player;

import spark.managers.PersistenceManager;

[Bindable]
public class Game {

    private var configModel:ConfigModel = ConfigModel.instance;
    
    public var teams:ArrayCollection = new ArrayCollection();
    public var players:ArrayCollection = new ArrayCollection();
    public var pointsToWin:int = configModel.pointsToWin;
    public var pegging:Boolean = true;
    public var counting:Boolean = false;
    public var crib:Boolean = false;
    public var completed:Boolean = false;
    public var winningTeam:Team;
    public var currentTeam:Team;
    public var currentPlayer:Player;
    public var started:Boolean = false;
    public var startDate:Date;
    public var endDate:Date;
    public var time:int = 0;
    public var round:int = 0;
    public var twoPlayers:Boolean = false;
    public var threePlayers:Boolean = false;
    public var fourPlayers:Boolean = false;
                                    
    private var teamQueue:Array;
    private var playerQueue:Array;

    public function Game(numberOfPlayers:int) {
        
        for (var x:int = 0; x < numberOfPlayers; x++) {
            players.addItem(new Player("player " + (x + 1)));
        }
        
        if(numberOfPlayers == 2) {
            twoPlayers = true;
            teams.addItem(new Team(players.getItemAt(0).name, [players.getItemAt(0)]));
            teams.addItem(new Team(players.getItemAt(1).name, [players.getItemAt(1)]));
        }

        if(numberOfPlayers == 3) {
            threePlayers = true;
            teams.addItem(new Team(players.getItemAt(0).name, [players.getItemAt(0)]));
            teams.addItem(new Team(players.getItemAt(1).name, [players.getItemAt(1)]));
            teams.addItem(new Team(players.getItemAt(2).name, [players.getItemAt(2)]));
        }

        if(numberOfPlayers == 4) {
            fourPlayers = true;
            teams.addItem(new Team("Team 1", [players.getItemAt(0), players.getItemAt(2)]));
            teams.addItem(new Team("Team 2", [players.getItemAt(1), players.getItemAt(3)]));
        }
    }
    
    public function get team1():Team {
        return teams.getItemAt(0) as Team;
    }
    
    public function get team2():Team {
        return teams.getItemAt(1) as Team;
    }
    
    public function get team3():Team {
        if(teams.length < 3) {
            return null;
        }
        else {
            return teams.getItemAt(2) as Team; 
        }
    }
    
    public function get player1():Player {
        return players.getItemAt(0) as Player;
    }
    
    public function get player2():Player {
        return players.getItemAt(1) as Player;
    } 
    
    public function get player3():Player {
        if(players.length < 3) {
            return null;
        }
        else {
            return players.getItemAt(2) as Player;
        }
    }
    
    public function get player4():Player {
        if(players.length < 4) {
            return null;
        }
        else {
            return players.getItemAt(3) as Player;
        }
    }

    public function start():void {

        started = true;
        startDate = new Date();
        startTimer();
        newRound();
    }

    public function resume():void {
        startTimer();
    }

    public function pause():void {
        stopTimer();
    }

    public function next():void {
        
        // set points to be complete
        if(pegging) {
            for each(var player:Player in players) {
                player.hand.peggingPoints.completed = true;
            }
        }
        else if(counting) {
            currentPlayer.hand.countingPoints.completed = true;
        }
        else if(crib) {
            currentPlayer.hand.cribPoints.completed = true;
        }

        
        // move on to next play in round
        if(completed) {
            stopTimer();
            endDate = new Date();
        }
        else if (pegging) {
            pegging = false;
            counting = true;
            currentTeam = teamQueue.shift() as Team;
            currentPlayer = playerQueue.shift() as Player;
        }
        else if (counting) {

            if (playerQueue.length > 0) {     
                currentTeam = teamQueue.shift() as Team;
                currentPlayer = playerQueue.shift() as Player;
            }
            else {
                counting = false;
                crib = true;
            }
        }
        else if(crib) {
            pegging = true;
            crib = false;

            for each(var player:Player in players) {
                player.hand.points.completed = true;
            }

            newRound();
        }
    }

    private function newRound():void {

        teamQueue = [];
        playerQueue = [];

        for (var x:int = 0; x < players.length; x++) {

            var teamIndex:int = (x + round) % teams.length;
            var team:Team = teams.getItemAt(teamIndex) as Team;

            var playerIndex:int = (x + round) % players.length;
            var player:Player = players.getItemAt(playerIndex) as Player;

            if (x == players.length - 1) {
                player.newCribHand();
            }
            else {
                player.newHand();
            }

            teamQueue.push(team);
            playerQueue.push(player);
        }

        round++;
    }
    
    private function setWinningTeam(team:Team):void {

        completed = true;
        winningTeam = team;
    }

    private function removeWinningTeam():void {

        completed = false;
        winningTeam = null;
    }

    public function addPeggingPoints(player:Player, amount:int):void {
        
        var team:Team = getTeam(player);
        
        if(team == winningTeam && amount < 0) {
            removeWinningTeam();
            currentPlayer.hand.points.completed = false;
        }

        if(team.score + amount >= pointsToWin) {
            
            player.addPeggingPoints(pointsToWin - team.score);    
            setWinningTeam(team);
            player.hand.points.completed = true;
        }
        else {
            player.addPeggingPoints(amount);
        }
    }

    public function addCountingPoints(amount:int):void {

        if(currentTeam == winningTeam && amount < 0) {
            removeWinningTeam();
            currentPlayer.hand.points.completed = false;
        }

        if(currentTeam.score + amount >= pointsToWin) {
                                                         
            currentPlayer.addCountingPoints(pointsToWin - currentTeam.score);    
            setWinningTeam(currentTeam);
            currentPlayer.hand.points.completed = true;
        }
        else {
            currentPlayer.addCountingPoints(amount);
        }
    }

    public function addCribPoints(amount:int):void {

        if(currentTeam == winningTeam && amount < 0) {
            removeWinningTeam();
            currentPlayer.hand.points.completed = false;
        }
        
        if(currentTeam.score + amount >= pointsToWin) {
                                                         
            currentPlayer.addCribPoints(pointsToWin - currentTeam.score);    
            setWinningTeam(currentTeam);
            currentPlayer.hand.points.completed = true;
        }
        else {
            currentPlayer.addCribPoints(amount);
        }
    }
    
    public function getTeam(player:Player):Team {

        for each(var team:Team in teams) {
            if(team.players.contains(player)) {
                return team;
            }
        }

        return null;
    }

    private var intervalId:uint;

    private function startTimer():void {

        var lastTime:int = getTimer();

        intervalId = setInterval(function ():void {

            var tempTime:int = getTimer();
            time += lastTime - tempTime;
            lastTime = tempTime;

        }, 1000);
    }

    private function stopTimer():void {

        clearInterval(intervalId);
    }
}
}
